"""
按照论文[1] Wang Gangyi, Li Jian, Wei Xinguo. Star identification based on hash map[J]. IEEE Sensors Journal, 2018, 18(4): 1591-1599

"""

import numpy as np
from .base import BinadHashVote
from itertools import product


class XuHashVote(BinadHashVote):
    def __init__(self, catalog_path, **kwargs):
        super().__init__(catalog_path, **kwargs)
        assert "N_b" in self.constants.keys()
        assert "dist" in self.constants.keys()
        self.N_b = self.constants["N_b"]
        self.max_dist = self.constants["dist"][1]
        self.min_dist = self.constants["dist"][0]

    def binad_descriptor(self, C1, C2, U1, U2, th=1, *args, **kwargs):
        """
        本函数需要并行化计算
        Arguments:
            param1 (np.ndarray) : ellipse parameters for (x^2, xy, y^2, x, y, 1), 6 x N array
            param2 (np.ndarray) : ellipse parameters for (x^2, xy, y^2, x, y, 1), 6 x N array
        """
        # 直接除以行列式是不对滴，参见文献
        # [1] Gros P. , Quan L. .Projective invariants for Vision[R].1992:47
        # from Xuliheng' methon
        if len(C1.shape) == 2:
            C1 = C1[None]
        if len(C2.shape) == 2:
            C2 = C2[None]
        assert C1.shape == C2.shape
        det = np.linalg.det(C1) / np.linalg.det(C2)
        I1 = np.trace(C1 @ np.linalg.inv(C2), axis1=1, axis2=2) ** 3 / det
        I2 = np.trace(C2 @ np.linalg.inv(C1), axis1=1, axis2=2) ** 3 * det
        # 量化
        qs = np.log(np.abs((I1, I2)))
        qs = np.int32(
            np.power((qs - self.min_dist) / (self.max_dist - self.min_dist), 4)
            * (self.N_b - 1)
        )
        # 根据误差阈值产生不同正负误差组合方式
        th = np.array(list(product(np.arange(-th, th + 1), repeat=2))).T
        # 输出计算所得哈希值
        return (qs[0] + th[0, :, None]) * self.N_b + (qs[1] + th[1, :, None])
